/*
    Contact info:
    bhepple@freeshell.org
    http://bhepple.freeshell.org/scrmgr

    Copyright (C) 1991-2008 Bob Hepple

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
/* SCRMGR - Convert data according to screen formats */

#include <stdio.h>
#include <getopt.h>
#include <setjmp.h>

#include "smlib.h"
#include "smio.h"

CHAR *smupdate_rcsid(void) {
    return("$Id: smupdate.c,v 1.6 2008/02/19 13:15:50 bhepple Exp $");
}

static CHAR	*progname, pname[9];
static CHAR	rev_string[] = "$Revision: 1.6 $";
int 		dirty_data = 0;
int		last_op = 0;
int		ignore_case = 0;
jmp_buf		NoMoreHeap;

static CHAR *usage_msg[] = {
"Converts data files according to 2 sets of SCRMGR screen formats",
"old_screenfile : old format for the data",
"new_screenfile : new format for the data",
"datafile       : data to be converted (STDIN is used if no file is given)",
"",
"New data is written to STDOUT",
NULL
};

void usage()
{
    CHAR **c;
    
    fprintf(stderr, "Revision %s of %s.\n", rev_string, pname);
    fprintf(stderr, "Usage: %s old_screenfile new_screenfile [datafile]\n", pname);
    
    c = usage_msg;
    while (*c) {
        fputs(*c, stderr);
        fputc('\n', stderr);
        c++;
    }
    exit(2);
}

/* Stubs to be overidden if needed (at the moment, only if your application
   uses field triggers) */

f_ptr sm_get_field_trigger ARG1(SM_FIELD, field)
{
    return(NULL);
}

void sm_error_exit ARG1(CHAR *, msg)
{
    sm_term();
    puts(msg);
    exit(1);
}

int process ARG1(FILE *, f)
{
    CHAR	*buf, *pos, *end;
    SM_SCREEN	in_screen = NULL, out_screen = NULL;
    SM_FIELD	in_field, *out_field;

    buf = alloca(SM_MAXREC);
    	
    if (sm_scrmgr_screens()->tagname == NULL)
        in_screen = *sm_first_scr(sm_scrmgr_screens());

    if (sm_user_screens()->tagname == NULL)
        out_screen = *sm_first_scr(sm_user_screens());

    pos = buf;
    while (fgets(pos, SM_MAXREC - (pos - buf), f) != NULL) {
	
        /* Bark at long lines - but try and continue */
        if (strlen(pos) >= SM_MAXREC - (pos - buf) - 1)
            sm_error("line too long");
        
        if ((end = strchr(pos, '\n')) != NULL)
            *end = 0;
        if ((end = strchr(pos, '\r')) != NULL)
            *end = 0;

        end = strchr(pos, 0);
        *(end + 1) = 0; /* extra 0 */
        if (*--end == '\\') {
            *end = 0;
            pos = end;
        } else {
            /* We have a record - translate it! */

            pos = buf;
	    
            if (sm_scrmgr_screens()->tagname)
                in_screen = sm_choose_scr(sm_scrmgr_screens(), buf);

            if (in_screen == NULL) {
                sm_message("Input: Can\'t pick a screen for:");
                sm_message(buf);
                continue;
            }
            sm_scr_init(in_screen, /* recursive = */ 1);
            sm_data_to_screen(in_screen, buf, 0);

            if (sm_user_screens()->tagname)
                out_screen = sm_scr_open(sm_user_screens(), 
                    in_screen->screen_name);
            if (out_screen == NULL) {
                fprintf(stderr, "Output: Can\'t pick a screen for: %s", buf);
                continue;
            }
            sm_scr_init(out_screen, /* recursive = */ 1);
	    
            /* Now, try to copy the data across ... */
            out_field = sm_first_fld(out_screen);

            while (out_field && *out_field) {
                in_field = sm_fld_open(in_screen, (*out_field)->field_name);
                if (in_field)
                    SM_FASSIGN((*out_field)->c_value, 
                        in_field->c_value,
                        (*out_field)->len < 0 ? abs((*out_field)->len): 0);
                out_field = sm_next_fld(out_field);
            }
		
            sm_screen_to_data(buf, out_screen);
            puts(buf);
        }
    }
    return(0);
}

int main ARG2(int, argc, CHAR **, argv)
{
    int		c, errors = 0;
    FILE	*data;

    alloca(SM_MAXREC);
    	
    progname = argv[0];
    fname(pname, progname);
    
    while ((c = getopt(argc, argv, "h?")) != EOF)
        switch (c) {
	    
        default:  
	    usage(); 
	    break;
        }

    if (setjmp(NoMoreHeap)) {
	fprintf(stderr, "Ran out of heap!\n");
	exit(1);
    }

    sm_init(0, argc, argv);
    smio_term(); /* Don't need curses */

    if ((optind >= argc) || (strlen(argv[optind]) == 0))
	usage();
    else /* Use 1st argument as screen file */
	if (sm_fopen(sm_scrmgr_screens(), argv[optind++]) == SM_ERROR) {
	    sm_error("Error reading screen file");
	    usage();
	}

    if ((optind >= argc) || (strlen(argv[optind]) == 0))
	usage();
    else /* Use 2nd arg as new screen format */
	if (sm_fopen(sm_user_screens(), argv[optind++]) == SM_ERROR) {
	    sm_error("Error reading screen file");
	    usage();
	}

    if ((optind >= argc) || (strlen(argv[optind]) == 0))
	process(stdin);
    else { /* Use 3rd arg as data */
	if ((data = fopen(argv[optind], "r")) == NULL)
	    sm_error_exit("Can\'t open datafile.");
	else
	    errors += process(data);
	fclose(data);
    }

    exit(errors);
}



/* For emacs:
 * Local Variables:
 * tab-width: 8
 * End:
 */
